package org.hs.phd.odi.tracking.tracker.particlefilter.core;

import java.util.LinkedList;

public class Particle<T> implements Cloneable {

	public final T initialState;
	private T currentState;

	private LinkedList<T> stateHistory;

	private int historySize;

	private float weight;

	public Particle(int historySize, T initialState) {
		this.historySize = historySize;
		this.initialState = initialState;
		this.currentState = initialState;
		
		stateHistory = new LinkedList<T>();
		for(int i = 0; i < historySize; i++){
			stateHistory.addFirst(initialState);
		}
		
		weight = 0;
	}

	private Particle(Particle<T> p, T newState) {
		this.historySize = p.historySize;
		this.initialState = p.initialState;
		this.currentState = newState;
		stateHistory = new LinkedList<T>();
		stateHistory.addAll(p.stateHistory);
		stateHistory.addFirst(p.currentState);
		stateHistory.removeLast();
		this.weight = 0;
	}

	
	@SuppressWarnings("unchecked")
	public Particle<T> clone() {
		try {
			return (Particle<T>) super.clone();
		} catch (CloneNotSupportedException e) {
			throw new Error(e);
		}
	}

	public T getCurrentState() {
		return currentState;
	}

	public T getPrevState(int historyIndex) {
		
		if(historyIndex >= historySize) throw new HistoryIndexOutofBoundsException( historyIndex + " >= " + historySize );
		
		return stateHistory.get(historyIndex);
	}

	public float getWeight() {
		return weight;
	}

	public void setWeight(float weight) {
		this.weight = weight;
	}

	public Particle<T> createNextGenerationParticle(T newState) {
		return new Particle<T>(this, newState);
	}

}
